home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Michael Fischbein.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that: (1) source distributions retain this entire copyright
- * notice and comment, and (2) distributions including binaries display
- * the following acknowledgement: ``This product includes software
- * developed by the University of California, Berkeley and its contributors''
- * in the documentation or other materials provided with the distribution
- * and in all advertising materials mentioning features or use of this
- * software. Neither the name of the University nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- #ifndef lint
- char copyright[] =
- "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
- All rights reserved.\n";
- #endif /* not lint */
-
- #ifndef lint
- static char sccsid[] = "@(#)ls.c 5.42 (Berkeley) 5/17/90";
- #endif /* not lint */
-
- #include "tweak.h"
- #include "bsd_extern.h"
- #include "client_def.h"
- #include "c_extern.h"
- #ifndef VMS
- #include <sys/ioctl.h>
- #endif
- #include "my-string.h"
- #include "ls.h"
-
- static char path[2*1024 + 1];
- static char *endofpath = path;
-
- int (*sortfcn)PROTO0((LS *, LS*));
- void (*printfcn)PROTO0((LS *, int));
-
- int termwidth = 80; /* default terminal width */
-
- /* flags */
- int f_accesstime; /* use time of last access */
- int f_column; /* columnated format */
- int f_group; /* show group ownership of a file */
- int f_ignorelink; /* indirect through symbolic link operands */
- int f_inode; /* print inode */
- int f_kblocks; /* print size in kilobytes */
- int f_listalldot; /* list . and .. as well */
- int f_listdir; /* list actual directory, not contents */
- int f_listdot; /* list files beginning with . */
- int f_longform; /* long listing format */
- int f_needstat; /* if need to stat files */
- int f_newline; /* if precede with newline */
- int f_nonprint; /* show unprintables as ? */
- int f_nosort; /* don't sort output */
- int f_recursive; /* ls subdirectories also */
- int f_reversesort; /* reverse whatever sort is used */
- int f_singlecol; /* use single column output */
- int f_size; /* list size in short listing */
- int f_statustime; /* use time of last mode change */
- int f_dirname; /* if precede with directory name */
- int f_timesort; /* sort by time vice name */
- int f_total; /* if precede with "total" line */
- int f_type; /* add type character for non-regular files */
-
- int tabdir PROTO2(LS *, lp, LS **, s_stats)
- {
- register RDIR *dirp;
- register int cnt, maxentry, maxlen;
- register char *p;
- struct rdirent *dp;
- unsigned long blocks;
- LS *stats;
-
- if (!(dirp = util_opendir("."))) {
- perror(lp->name);
- return(0);
- }
- blocks = maxentry = maxlen = 0;
- stats = NULL;
- for (cnt = 0; dp = util_readdir(dirp);) {
- /* this does -A and -a */
- p = dp->d_name;
- if (p[0] == '.') {
- if (!f_listdot) continue;
- if (!f_listalldot && (!p[1] || p[1] == '.' && !p[2])) continue;
- }
- if (cnt == maxentry) {
- #define DEFNUM 256
- maxentry += DEFNUM;
- if(stats) {
- *s_stats = stats = (LS *)realloc((char *)stats,
- (unsigned int)maxentry * sizeof(LS));
- if (!*s_stats) nomem();
- } else {
- *s_stats = stats = (LS *)malloc((unsigned int)maxentry * sizeof(LS));
- if (!*s_stats) nomem();
- }
- }
- if (f_needstat && util_stat(dp->d_name, &stats[cnt].lstat)) {
- /*
- * don't exit -- this could be an NFS mount that has
- * gone away. Flush stdout so the messages line up.
- */
- (void)fflush(stdout);
- perror(dp->d_name);
- continue;
- }
- stats[cnt].name = dp->d_name;
-
- /*
- * get the inode from the directory, so the -f flag
- * works right.
- */
- #ifndef VMS
- stats[cnt].lstat.st_ino = dp->d_fileno;
- #endif
-
- /* save name length for -C format */
- stats[cnt].len = dp->d_namlen;
-
- /* calculate number of blocks if -l/-s formats */
- if (f_longform || f_size) blocks += (stats[cnt].lstat.st_size+1023)/1024;
-
- /* save max length if -C format */
- if (f_column && maxlen < (int)dp->d_namlen) maxlen = dp->d_namlen;
- ++cnt;
- }
- (void)util_closedir(dirp);
-
- if (cnt) {
- stats[0].lstat.st_btotal = blocks;
- stats[0].lstat.st_maxlen = maxlen;
- } else if (stats) {
- (void)free((char *)stats);
- }
- return(cnt);
- }
-
- static int displaydir PROTO0((LS *, register int));
-
- static int subdir PROTO1(LS *, lp)
- {
- LS *stats;
- int num;
-
- if (f_newline) (void)putchar('\n');
- if (f_dirname) (void)printf("%s:\n", path);
-
- if (util_cd2(lp->name)) {
- perror(lp->name);
- return;
- }
- if (num = tabdir(lp, &stats)) {
- displaydir(stats, num);
- (void)free((char *)stats);
- }
- if (util_cd2("..")) {
- perror("..");
- ls_bad(1);
- }
- }
-
- static int displaydir PROTO2(LS *, stats, register int, num)
- {
- register char *p, *savedpath;
- LS *lp;
-
- if (num > 1 && !f_nosort) {
- unsigned long save1, save2;
-
- save1 = stats[0].lstat.st_btotal;
- save2 = stats[0].lstat.st_maxlen;
- qsort((char *)stats, num, sizeof(LS), sortfcn);
- stats[0].lstat.st_btotal = save1;
- stats[0].lstat.st_maxlen = save2;
- }
-
- printfcn(stats, num);
-
- if (f_recursive) {
- savedpath = endofpath;
- for (lp = stats; num--; ++lp) {
- if (!(S_ISDIR(lp->lstat.st_mode))) continue;
- p = lp->name;
- if (p[0] == '.' && (!p[1] || p[1] == '.' && !p[2])) continue;
- if (endofpath != path && endofpath[-1] != '/') *endofpath++ = '/';
- for (; *endofpath = *p++; ++endofpath);
- f_newline = f_dirname = f_total = 1;
- subdir(lp);
- *(endofpath = savedpath) = '\0';
- }
- }
- }
-
- static int doargs PROTO2(int, argc, char **, argv)
- {
- register LS *dstatp, *rstatp;
- register int cnt, dircnt, dirmax, maxlen, regcnt, regmax;
- LS *dstats, *rstats;
- struct stat sb;
- char top[2*1024 + 1], **av, *av2[2];
- unsigned long blocks;
-
- /*
- * walk through the operands, building separate arrays of LS
- * structures for directory and non-directory files.
- */
- dstats = rstats = NULL;
- dirmax = regmax = 0;
-
- for (dircnt = regcnt = 0; *argv; ++argv) {
- if(!(av = glob(*argv))) {
- av = av2;
- av2[0] = *argv;
- av2[1] = 0;
- }
-
- for( ; *av; av++) {
- if (util_stat(*av, &sb)) {
- perror(*av);
- if (errno == ENOENT) continue;
- ls_bad(1);
- }
- if ((S_ISDIR(sb.st_mode)) && !f_listdir) {
- if(dirmax == dircnt) {
- dirmax += 10;
- if (!dstats) {
- dstatp = dstats = (LS *)emalloc(dirmax * (sizeof(LS)));
- } else {
- dstats = (LS *)realloc(dstats, dirmax * (sizeof(LS)));
- dstatp = dstats + dircnt;
- }
- }
- dstatp->name = *av;
- dstatp->lstat = sb;
- ++dstatp;
- ++dircnt;
- } else {
- if(regmax == regcnt) {
- regmax += 10;
- if (!rstats) {
- blocks = 0;
- maxlen = -1;
- rstatp = rstats = (LS *)emalloc(regmax * (sizeof(LS)));
- } else {
- rstats = (LS *)realloc(rstats, regmax * (sizeof(LS)));
- rstatp = rstats + regcnt;
- }
- }
- rstatp->name = *av;
- rstatp->lstat = sb;
-
- /* save name length for -C format */
- rstatp->len = strlen(*av);
-
- if (f_nonprint) prcopy(*av, *av, rstatp->len);
-
- /* calculate number of blocks if -l/-s formats */
- if (f_longform || f_size) blocks += (sb.st_size + 1023)/1024;
-
- /* save max length if -C format */
- if (f_column && maxlen < rstatp->len) maxlen = rstatp->len;
-
- ++rstatp;
- ++regcnt;
- }
- }
- }
- /* display regular files */
- if (regcnt) {
- rstats[0].lstat.st_btotal = blocks;
- rstats[0].lstat.st_maxlen = maxlen;
- displaydir(rstats, regcnt);
- f_newline = f_dirname = 1;
- }
- /* display directories */
- if (dircnt) {
- register char *p;
-
- f_total = 1;
- if (dircnt > 1) {
- (void)util_getwd(top);
- qsort((char *)dstats, dircnt, sizeof(LS), sortfcn);
- f_dirname = 1;
- }
- for (cnt = 0; cnt < dircnt; ++dstats) {
- for (endofpath = path, p = dstats->name;
- *endofpath = *p++; ++endofpath);
- subdir(dstats);
- f_newline = 1;
- if (++cnt < dircnt && util_cd2(top)) {
- perror(top);
- ls_bad(1);
- }
- }
- }
- }
-
- void fls_main PROTO2(int, argc, char **, argv)
- {
- extern int optind;
- int ch;
- char *p;
-
- /* terminal defaults to -Cq, non-terminal defaults to -1 */
- if (isatty(1)) {
- f_nonprint = 1;
- termwidth = 80;
- #ifdef TIOCGWINSZ
- {
- struct winsize win;
- if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
- if (p = (char *)getenv("COLUMNS")) termwidth = atoi(p);
- } else termwidth = win.ws_col;
- }
- #endif
- f_column = 1;
- } else f_singlecol = 1;
-
- /* root is -A automatically */
- if (!getuid()) f_listdot = 1;
-
- while ((ch = getopt(argc, argv, "1ACFLRacdfgiklqrstu")) != EOF) {
- switch (ch) {
- /*
- * -1, -C and -l all override each other
- * so shell aliasing works right
- */
- case '1':
- f_singlecol = 1;
- f_column = f_longform = 0;
- break;
- case 'C':
- f_column = 1;
- f_longform = f_singlecol = 0;
- break;
- case 'l':
- f_longform = 1;
- f_column = f_singlecol = 0;
- break;
- /* -c and -u override each other */
- case 'c':
- f_statustime = 1;
- f_accesstime = 0;
- break;
- case 'u':
- f_accesstime = 1;
- f_statustime = 0;
- break;
- case 'F':
- f_type = 1;
- break;
- case 'L':
- f_ignorelink = 1;
- break;
- case 'R':
- f_recursive = 1;
- break;
- case 'a':
- f_listalldot = 1;
- /* FALLTHROUGH */
- case 'A':
- f_listdot = 1;
- break;
- case 'd':
- f_listdir = 1;
- break;
- case 'f':
- f_nosort = 1;
- break;
- case 'g':
- f_group = 1;
- break;
- case 'i':
- f_inode = 1;
- break;
- case 'k':
- f_kblocks = 1;
- break;
- case 'q':
- f_nonprint = 1;
- break;
- case 'r':
- f_reversesort = 1;
- break;
- case 's':
- f_size = 1;
- break;
- case 't':
- f_timesort = 1;
- break;
- case '?':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- /* -d turns off -R */
- if (f_listdir)
- f_recursive = 0;
-
- /* if need to stat files */
- f_needstat = f_longform || f_recursive || f_timesort || f_size || f_type;
-
- /* select a sort function */
- if (f_reversesort) {
- if (!f_timesort) sortfcn = revnamecmp;
- else if (f_accesstime) sortfcn = revacccmp;
- else if (f_statustime) sortfcn = revstatcmp;
- else sortfcn = revmodcmp; /* use modification time */
- } else {
- if (!f_timesort) sortfcn = namecmp;
- else if (f_accesstime) sortfcn = acccmp;
- else if (f_statustime) sortfcn = statcmp;
- else sortfcn = modcmp; /* use modification time */
- }
-
- /* select a print function */
- if (f_singlecol) printfcn = printscol;
- else if (f_longform) printfcn = printlong;
- else printfcn = printcol;
-
- if (!argc) {
- argc = 1;
- argv[0] = ".";
- argv[1] = NULL;
- }
- doargs(argc, argv);
- }
-
-